/*
 * Copyright (C) 2004-2006 nickyb@users.sourceforge.net
 * 
 * This file is part of FreeQueryBuilder (http://querybuilder.sourceforge.net)
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

package net.sourceforge.querybuilder;

import java.awt.event.ActionEvent;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;

import java.util.Arrays;
import java.util.StringTokenizer;

import javax.swing.AbstractAction;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.border.LineBorder;

public class QueryBuilder extends BasePanel
{
	public static boolean useIdentifierQuote = true;
	public static String identifierQuoteString 	= "\"";
	
	private boolean joinMode;
	private Connection connection;

	QuerySyntax  syntax;
	QueryClauses clauses;
	QueryDiagram diagram;
	QueryListbar listbar;
	QueryBrowser browser;
	
	public QueryBuilder()
	{
		this(null);
	}

	public QueryBuilder(Connection connection)
	{
		super(2,2);
		
		this.getActionMap().put("clear-diagram"		,new ActionClear());
		this.getActionMap().put("change-work-mode"	,new ActionChangeWorkMode());
		
		JTabbedPane tabs = new JTabbedPane();
		tabs.setBorder(LineBorder.createGrayLineBorder());
		tabs.addTab("syntax",syntax = new QuerySyntax(this));
		tabs.addTab("browse",browser = new QueryBrowser(this));
		
		JScrollPane scroll = new JScrollPane(diagram = new QueryDiagram(this));
		scroll.getVerticalScrollBar().setUnitIncrement(25);
		
		JSplitPane splitB = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
		splitB.setOneTouchExpandable(true);
		splitB.setDividerLocation(250);
		splitB.setLeftComponent(tabs);
		splitB.setRightComponent(clauses = new QueryClauses(this));
		
		JSplitPane split = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
		split.setTopComponent(scroll);
		split.setBottomComponent(splitB);
		split.setOneTouchExpandable(true);
		
		setComponentNorth(listbar = new QueryListbar(this));
		setComponentCenter(split);
		
		this.addComponentListener(new ComponentAdapter()
		{
			public void componentResized(ComponentEvent evt)
			{
				JSplitPane split = (JSplitPane)QueryBuilder.this.getComponent(1);
				split.setDividerLocation(0.75);
				split.validate();
			} 
		});
		
		this.setConnection(connection);
		this.transferFocus();
	}
	
	void changeWorkMode()
	{
		joinMode = !joinMode;
		diagram.workModeChanged();
	}
	
	boolean isJoinMode()
	{
		return joinMode;
	}
	
	public void clear()
	{
		diagram.closeAllFrames();
		clauses.clear();
		syntax.clear();
	}
	
	String[] allFunctions = new String[0];
	private void addFunctions(String tokenize)
	{
		StringTokenizer st = new StringTokenizer(tokenize,",");
		
		String[] appo = new String[st.countTokens() + allFunctions.length];
		System.arraycopy(allFunctions,0,appo,0,allFunctions.length);
		
		for(int i=allFunctions.length; st.hasMoreTokens(); i++)
			appo[i] = st.nextToken();
		
		allFunctions = appo;
	}
	
	private void loadFunctions()
		throws SQLException
	{
		DatabaseMetaData dbmd = connection.getMetaData();
		
		addFunctions(dbmd.getNumericFunctions());
		addFunctions(dbmd.getStringFunctions());
		addFunctions(dbmd.getSystemFunctions());
		addFunctions(dbmd.getTimeDateFunctions());
		
		Arrays.sort(allFunctions);
	}
	
	public String[] getAllFunctions()
	{
		return allFunctions;
	}
	
	public void add(QueryTokens.Table table, boolean autojoin)
	{
		DiagramLoader.run(diagram,table);
	}

	public QueryModel getModelClone()
	{
		if(syntax.querymodel==null) return null;
		return (QueryModel)syntax.querymodel.clone();
	}

	public Connection getConnection()
	{
		return connection;
	}
	
	public void setConnection(Connection connection)
	{
		this.allFunctions = new String[0];
		this.connection = connection;
		this.clear();
		
		try
		{
			browser.connectionChanged();
			
			if(connection!=null)
			{
				QueryBuilder.identifierQuoteString = connection.getMetaData().getIdentifierQuoteString();
				QueryTokens.maxColumnNameLength = connection.getMetaData().getMaxColumnNameLength();
				
				loadFunctions();
			}
			
		}
		catch(SQLException sqle)
		{
			System.out.println("[ QueryBuilder::setConnection ]\n" + sqle);
		}
	}

	public boolean jdbcUseSchema() throws SQLException
	{
		if(connection!=null)
		{
			String term = connection.getMetaData().getSchemaTerm();
			return term!=null && term.length()>0;
		}
		
		return false;
	}
	
    private class ActionChangeWorkMode extends AbstractAction
    {
        ActionChangeWorkMode()
        {
        	putValue(NAME,"join");
        	putValue(SHORT_DESCRIPTION,"join");
        }
        
        public void actionPerformed(ActionEvent arg0)
        {
            QueryBuilder.this.changeWorkMode();
        }
    }
    
    private class ActionClear extends AbstractAction
    {
        ActionClear()
        {
        	putValue(NAME,"clear diagram");
        	putValue(SHORT_DESCRIPTION,"clear diagram");
        }
        
        public void actionPerformed(ActionEvent arg0)
        {
            QueryBuilder.this.clear();
        }
    }
}